package diona.search.yasearch

import net.liftweb.common.Logger
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import java.util.Locale
import xml.{NodeSeq, Node, XML}
import java.net.{URLEncoder, URL}
import diona.search.PostInfo

/**
 * User: anton
 * Date: 06.07.11 22:20
 */
object YaBlogsSearch extends Logger
{
  private val dateFormatter = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withLocale(Locale.US)

  private val baseUrl = "http://blogs.yandex.ru/search.rss"

  def buildUrl(query: String, from: Option[DateTime], to: Option[DateTime]): String =
  {
    val result = new StringBuilder()
    result ++= baseUrl ++= "?text=" ++= URLEncoder.encode(query, "utf-8") ++= "&numdoc=100"
    from.foreach(d => result ++= ("&" + toParams("from", d)))
    to.foreach(d => result ++= ("&" + toParams("to", d)))

    result.toString()
  }

  def buildUrl(query: String): String = buildUrl(query, None, None)

  def searchByUrl(url: String): (Option[String], Seq[PostInfo]) =
  {
    val rss = XML.load(new URL(url))
    val posts = for {
      item <- rss \ "channel" \ "item"
      val author = (item \ "author") match {
        case Seq() => None
        case Seq(a: Node, _) => Some(a.text)
        case a: NodeSeq => Some(a.text)
      }
      val title = (item \ "title").text
      val pubDate = (item \ "pubDate").text
      val link = (item \ "link").text
      val description = (item \ "description").text
      val isComment = !(item \ "is-comment").isEmpty
    } yield
      new PostInfo(
        url = link,
        tstamp = dateFormatter.parseDateTime(pubDate),
        isComment = isComment,
        snippet = Some(description),
        author = author,
        title = Some(title)
      )

    val link = getLink(rss \ "channel" \ "link")
    val moreUrl = getLink(rss \ "channel" \ "more")

    val nextUrl = if (link == moreUrl) None else moreUrl

    nextUrl -> posts
  }

  private def getLink(linkNode: NodeSeq): Option[String] = {
    linkNode.headOption.map(
      _.text.replaceFirst("http://blogs.yandex.ru/search.xml", "http://blogs.yandex.ru/search.rss")
    )
  }

  @volatile var search: (String, Option[DateTime], Option[DateTime]) => (Option[String], Seq[PostInfo]) =
    (query, from, to) => {
      val url: String = buildUrl(query, from, to)
      searchByUrl(url)
    }

  def search(query: String): Seq[PostInfo] = search(query, None, None)._2

  def searchWithNext(query: String): (Option[String], Seq[PostInfo]) = search(query, None, None)

  private def toParams(prefix: String, date: DateTime): String =
  {
    String.format("%1$s_day=%2$td&%1$s_month=%2$tm&%1$s_year=%2$tY", prefix, date.toDate)
  }
}